package com.zn.opit.shirodemo.config.shiro;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zn.opit.shirodemo.domain.consts.CommonConst;
import com.zn.opit.shirodemo.domain.entity.SysUserEntity;
import com.zn.opit.shirodemo.domain.enums.SysUserStatus;
import com.zn.opit.shirodemo.domain.po.SysRolePO;
import com.zn.opit.shirodemo.exception.ShiroDemoException;
import com.zn.opit.shirodemo.exception.ShiroDemoExceptionTypes;
import com.zn.opit.shirodemo.service.SysRoleService;
import com.zn.opit.shirodemo.service.SysUserService;
import com.zn.opit.shirodemo.utils.RedisUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysRoleService roleService;

    @Resource
    private RedisUtil redisUtil;

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        List<SysRolePO> roles = redisUtil.get(CommonConst.LOGIN_USER_CACHE_KEY + username);
        if (null == roles) {
            roles = roleService.getRolesByUsername(username);
            redisUtil.set(CommonConst.LOGIN_USER_CACHE_KEY + username, roles);
        }
        if (roles == null) {
            roles = new ArrayList<>();
        }
        roles.forEach(role -> {
            authorizationInfo.addRole(role.getRoleId());
            role.getPerms().forEach(perm -> authorizationInfo.addStringPermission(perm.getPermId()));
        });
        return authorizationInfo;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = ((UsernamePasswordToken) token).getUsername();
        SysUserEntity user = userService.getOne(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getUserId, username));
        if (null == user) {
            throw new ShiroDemoException(ShiroDemoExceptionTypes.LOGIN_USER_CREDENTIALS_FAILED);
        } else if (SysUserStatus.LOCKED.getCode().equals(user.getStatus())) {
            throw new ShiroDemoException(ShiroDemoExceptionTypes.LOGIN_USER_BE_LOCKED);
        }
        return new SimpleAuthenticationInfo(username, user.getPassword(), ByteSource.Util.bytes(username), getName());
    }
}
